home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / me310.zip / UE310C.ZIP / UNIX.C < prev    next >
C/C++ Source or Header  |  1989-08-22  |  15KB  |  611 lines

  1. /*    UNIX.C:    Operating specific I/O and Spawning functions
  2.         under UNIX V7, BSD4.2/3, System V, SUN OS and SCO XENIX
  3.         for MicroEMACS 3.10
  4.         (C)opyright 1988 by Daniel M. Lawrence
  5. */
  6.  
  7. #include        <stdio.h>
  8. #include    "estruct.h"
  9. #include    "etype.h"
  10. #if    V7 | BSD | USG | HPUX | SUN | XENIX
  11. #include        "edef.h"
  12. #include    "elang.h"
  13.  
  14. #if    USG | HPUX | SUN | XENIX            /* System V */
  15. #include    <signal.h>
  16. #include    <termio.h>
  17. #include    <fcntl.h>
  18. #include    <sys/ndir.h>
  19. #include    <sys/types.h>
  20. #include    <sys/stat.h>
  21. int kbdflgs;            /* saved keyboard fd flags    */
  22. int kbdpoll;            /* in O_NDELAY mode            */
  23. int kbdqp;            /* there is a char in kbdq    */
  24. char kbdq;            /* char we've already read    */
  25. struct    termio    otermio;    /* original terminal characteristics */
  26. struct    termio    ntermio;    /* charactoristics to use inside */
  27. #endif
  28.  
  29. #if V7 | BSD
  30. /* I hit a system name here... we have to define it back to what
  31.    emacs expacts */
  32. #undef    CTRL
  33. #include        <sgtty.h>        /* for stty/gtty functions */
  34. #include    <signal.h>
  35. #include    <sys/types.h>
  36. #include    <sys/dir.h>
  37. #include    <sys/stat.h>
  38. struct  sgttyb  ostate;          /* saved tty state */
  39. struct  sgttyb  nstate;          /* values for editor mode */
  40. struct tchars    otchars;    /* Saved terminal special character set */
  41. struct tchars    ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  42. #undef    CTRL
  43. #define CTRL    0x0100        /* Control flag, or'ed in        */
  44.  
  45. #if BSD
  46. #include <sys/ioctl.h>        /* to get at the typeahead */
  47. extern    int rtfrmshell();    /* return from suspended shell */
  48. #define    TBUFSIZ    128
  49. char tobuf[TBUFSIZ];        /* terminal output buffer */
  50. #endif
  51. #endif
  52.  
  53. #if     V7 | USG | HPUX | SUN | XENIX | BSD
  54. #include        <signal.h>
  55. extern int vttidy();
  56. #endif
  57.  
  58. /*
  59.  * This function is called once to set up the terminal device streams.
  60.  * On VMS, it translates TT until it finds the terminal, then assigns
  61.  * a channel to it and sets it raw. On CPM it is a no-op.
  62.  */
  63. ttopen()
  64.  
  65. {
  66. #if    USG | HPUX | SUN | XENIX
  67.     ioctl(0, TCGETA, &otermio);    /* save old settings */
  68.     ntermio.c_iflag = 0;        /* setup new settings */
  69.     ntermio.c_oflag = 0;
  70.     ntermio.c_cflag = otermio.c_cflag;
  71.     ntermio.c_lflag = 0;
  72.     ntermio.c_line = otermio.c_line;
  73.     ntermio.c_cc[VMIN] = 1;
  74.     ntermio.c_cc[VTIME] = 0;
  75.     ioctl(0, TCSETAW, &ntermio);    /* and activate them */
  76.     kbdflgs = fcntl( 0, F_GETFL, 0 );
  77.     kbdpoll = FALSE;
  78. #endif
  79.  
  80. #if     V7 | BSD
  81.         gtty(0, &ostate);                       /* save old state */
  82.         gtty(0, &nstate);                       /* get base of new state */
  83.         nstate.sg_flags |= RAW;
  84.         nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
  85.         stty(0, &nstate);                       /* set mode */
  86.     ioctl(0, TIOCGETC, &otchars);        /* Save old characters */
  87.     ioctl(0, TIOCSETC, &ntchars);        /* Place new character into K */
  88. #if    BSD
  89.     /* provide a smaller terminal output buffer so that
  90.        the type ahead detection works better (more often) */
  91.     setbuffer(stdout, &tobuf[0], TBUFSIZ);
  92.     signal(SIGTSTP,SIG_DFL);    /* set signals so that we can */
  93.     signal(SIGCONT,rtfrmshell);    /* suspend & restart emacs */
  94. #endif
  95. #endif
  96.     /* on all screens we are not sure of the initial position
  97.        of the cursor                    */
  98.     ttrow = 999;
  99.     ttcol = 999;
  100. }
  101.  
  102. /*
  103.  * This function gets called just before we go back home to the command
  104.  * interpreter.
  105.  */
  106.  
  107. ttclose()
  108.  
  109. {
  110. #if    USG | HPUX | SUN | XENIX
  111.     ioctl(0, TCSETA, &otermio);    /* restore terminal settings */
  112.     fcntl(0, F_SETFL, kbdflgs);
  113. #endif
  114.  
  115. #if     V7 | BSD
  116.         stty(0, &ostate);
  117.     ioctl(0, TIOCSETC, &otchars);    /* Place old character into K */
  118. #endif
  119. }
  120.  
  121. /*
  122.  * Write a character to the display. On VMS, terminal output is buffered, and
  123.  * we just put the characters in the big array, after checking for overflow.
  124.  * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
  125.  * MS-DOS (use the very very raw console output routine).
  126.  */
  127. ttputc(c)
  128. {
  129. #if     V7 | USG | HPUX | SUN | XENIX | BSD
  130.         fputc(c, stdout);
  131. #endif
  132. }
  133.  
  134. /*
  135.  * Flush terminal buffer. Does real work where the terminal output is buffered
  136.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  137.  */
  138. ttflush()
  139. {
  140. #if     V7 | USG | HPUX | SUN | XENIX | BSD
  141.         fflush(stdout);
  142. #endif
  143. }
  144.  
  145. /*    TTGETC:    Read a character from the terminal, performing no
  146.         editing and doing no echo at all. More complex in VMS
  147.         that almost anyplace else, which figures. Very simple
  148.         on CPM, because the system can do exactly what you
  149.         want.
  150. */
  151.  
  152. ttgetc()
  153.  
  154. {
  155. #if     V7 | BSD
  156.     char c;
  157.  
  158.         read(0, &c, 1);
  159.     return(255 & (int)c);
  160. #endif
  161.  
  162. #if    USG | HPUX | SUN | XENIX
  163.     if (kbdqp)
  164.         kbdqp = FALSE;
  165.     else {
  166.         /* we desperatly seek a character so we turn off
  167.            the NO_DELAY flag and simply wait for the bastard*/
  168.         if (fcntl(0, F_SETFL, kbdflgs) < 0 && kbdpoll)
  169.             return(FALSE);
  170.         kbdpoll = FALSE;    /* no polling */
  171.         read(0, &kbdq, 1);    /* wait until we get a character */
  172.     }
  173.     return(kbdq & 255);
  174. #endif
  175. }
  176.  
  177. #if    TERMCAP & (USG | HPUX | SUN | XENIX)
  178. /* get a character with timeout */
  179. mttgetc()
  180.  
  181. {
  182.     struct termio tset;
  183.     int status;
  184.     char c,c_eof,c_eol;
  185.     int i,count;
  186.     long trns;
  187.  
  188.     fcntl(0,F_SETFL,O_NDELAY);
  189.     for(count=150; count != 0 ; --count) {
  190.         i = read(0,&c,1);         /* get a character */
  191.         if (i == 1)            /* got a char */
  192.             break;
  193.     }
  194.     fcntl(0,F_SETFL,0);
  195.     if (i<= 0)    /* timeout error */
  196.         return(-1);
  197.     i = c;
  198.     return(i & 0xff);        /* return character */
  199. }
  200. #endif
  201.  
  202. #if    TYPEAH
  203. /* typahead:    Check to see if any characters are already in the
  204.         keyboard buffer
  205. */
  206.  
  207. typahead()
  208.  
  209. {
  210. #if    BSD
  211.     int x;    /* holds # of pending chars */
  212.  
  213.     return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
  214. #endif
  215.  
  216. #if    USG | HPUX | SUN | XENIX
  217.     if (!kbdqp) {
  218.         /* set O_NDELAY */
  219.         if (fcntl(0, F_SETFL, kbdflgs | O_NDELAY) < 0 && kbdpoll)
  220.             return(FALSE);
  221.         kbdpoll = TRUE;
  222.         kbdqp = (1 == read(0, kbdq, 1));
  223.     }
  224.     return(kbdqp);
  225. #endif
  226. #if    V7
  227.     return(FALSE);
  228. #endif
  229. }
  230. #endif
  231.  
  232. /*
  233.  * Create a subjob with a copy of the command intrepreter in it. When the
  234.  * command interpreter exits, mark the screen as garbage so that you do a full
  235.  * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
  236.  * Under some (unknown) condition, you don't get one free when DCL starts up.
  237.  */
  238. spawncli(f, n)
  239. {
  240.         register char *cp;
  241.         char    *getenv();
  242.  
  243.     /* don't allow this command if restricted */
  244.     if (restflag)
  245.         return(resterr());
  246.  
  247.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  248.         TTflush();
  249.         TTclose();                              /* stty to old settings */
  250.         if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  251.                 system(cp);
  252.         else
  253. #if    BSD
  254.                 system("exec /bin/csh");
  255. #else
  256.                 system("exec /bin/sh");
  257. #endif
  258.         sgarbf = TRUE;
  259.     sleep(2);
  260.         TTopen();
  261.         return(TRUE);
  262. }
  263.  
  264. #if    BSD
  265.  
  266. bktoshell()        /* suspend MicroEMACS and wait to wake up */
  267. {
  268.     int pid;
  269.  
  270.     vttidy();
  271.     pid = getpid();
  272.     kill(pid,SIGTSTP);
  273. }
  274.  
  275. rtfrmshell()
  276. {
  277.     TTopen();
  278.     curwp->w_flag = WFHARD;
  279.     sgarbf = TRUE;
  280. }
  281. #endif
  282.  
  283. /*
  284.  * Run a one-liner in a subjob. When the command returns, wait for a single
  285.  * character to be typed, then mark the screen as garbage so a full repaint is
  286.  * done. Bound to "C-X !".
  287.  */
  288. spawn(f, n)
  289. {
  290.         register int    s;
  291.         char            line[NLINE];
  292.  
  293.     /* don't allow this command if restricted */
  294.     if (restflag)
  295.         return(resterr());
  296.  
  297.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  298.                 return(s);
  299.         TTputc('\n');                /* Already have '\r'    */
  300.         TTflush();
  301.         TTclose();                              /* stty to old modes    */
  302.         system(line);
  303.         TTopen();
  304.         TTflush();
  305.     /* if we are interactive, pause here */
  306.     if (clexec == FALSE) {
  307.             mlputs(TEXT6);
  308. /*                     "\r\n\n[End]" */
  309.             tgetc();
  310.         }
  311.         sgarbf = TRUE;
  312.         return(TRUE);
  313. }
  314.  
  315. /*
  316.  * Run an external program with arguments. When it returns, wait for a single
  317.  * character to be typed, then mark the screen as garbage so a full repaint is
  318.  * done. Bound to "C-X $".
  319.  */
  320.  
  321. execprg(f, n)
  322.  
  323. {
  324.         register int    s;
  325.         char            line[NLINE];
  326.  
  327.     /* don't allow this command if restricted */
  328.     if (restflag)
  329.         return(resterr());
  330.  
  331.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  332.                 return(s);
  333.         TTputc('\n');                /* Already have '\r'    */
  334.         TTflush();
  335.         TTclose();                              /* stty to old modes    */
  336.         system(line);
  337.         TTopen();
  338.         mlputs(TEXT188);                        /* Pause.               */
  339. /*             "[End]" */
  340.         TTflush();
  341.         while ((s = tgetc()) != '\r' && s != ' ')
  342.                 ;
  343.         sgarbf = TRUE;
  344.         return(TRUE);
  345. }
  346.  
  347. /*
  348.  * Pipe a one line command into a window
  349.  * Bound to ^X @
  350.  */
  351. pipecmd(f, n)
  352. {
  353.         register int    s;    /* return status from CLI */
  354.     register WINDOW *wp;    /* pointer to new window */
  355.     register BUFFER *bp;    /* pointer to buffer to zot */
  356.         char    line[NLINE];    /* command line send to shell */
  357.     static char bname[] = "command";
  358.  
  359.     static char filnam[NFILEN] = "command";
  360.  
  361.     /* don't allow this command if restricted */
  362.     if (restflag)
  363.         return(resterr());
  364.  
  365.     /* get the command to pipe in */
  366.         if ((s=mlreply("@", line, NLINE)) != TRUE)
  367.                 return(s);
  368.  
  369.     /* get rid of the command output buffer if it exists */
  370.         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
  371.         /* try to make sure we are off screen */
  372.         wp = wheadp;
  373.         while (wp != NULL) {
  374.             if (wp->w_bufp == bp) {
  375.                 onlywind(FALSE, 1);
  376.                 break;
  377.             }
  378.             wp = wp->w_wndp;
  379.         }
  380.         if (zotbuf(bp) != TRUE)
  381.  
  382.             return(FALSE);
  383.     }
  384.  
  385.         TTputc('\n');                /* Already have '\r'    */
  386.         TTflush();
  387.         TTclose();                              /* stty to old modes    */
  388.     strcat(line,">");
  389.     strcat(line,filnam);
  390.         system(line);
  391.         TTopen();
  392.         TTflush();
  393.         sgarbf = TRUE;
  394.         s = TRUE;
  395.  
  396.     if (s != TRUE)
  397.         return(s);
  398.  
  399.     /* split the current window to make room for the command output */
  400.     if (splitwind(FALSE, 1) == FALSE)
  401.             return(FALSE);
  402.  
  403.     /* and read the stuff in */
  404.     if (getfile(filnam, FALSE) == FALSE)
  405.         return(FALSE);
  406.  
  407.     /* make this window in VIEW mode, update all mode lines */
  408.     curwp->w_bufp->b_mode |= MDVIEW;
  409.     wp = wheadp;
  410.     while (wp != NULL) {
  411.         wp->w_flag |= WFMODE;
  412.         wp = wp->w_wndp;
  413.     }
  414.  
  415.     /* and get rid of the temporary file */
  416.     unlink(filnam);
  417.     return(TRUE);
  418. }
  419.  
  420. rename(old, new)    /* change the name of a file */
  421.  
  422. char *old;    /* original file name */
  423. char *new;    /* new file name */
  424.  
  425. {
  426.     link(old, new);
  427.     unlink(old);
  428. }
  429.  
  430. /*
  431.  * filter a buffer through an external DOS program
  432.  * Bound to ^X #
  433.  */
  434. filter(f, n)
  435.  
  436. {
  437.         register int    s;    /* return status from CLI */
  438.     register BUFFER *bp;    /* pointer to buffer to zot */
  439.         char line[NLINE];    /* command line send to shell */
  440.     char tmpnam[NFILEN];    /* place to store real file name */
  441.     static char bname1[] = "fltinp";
  442.  
  443.     static char filnam1[] = "fltinp";
  444.     static char filnam2[] = "fltout";
  445.  
  446.     /* don't allow this command if restricted */
  447.     if (restflag)
  448.         return(resterr());
  449.  
  450.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  451.         return(rdonly());    /* we are in read only mode    */
  452.  
  453.     /* get the filter name and its args */
  454.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  455.                 return(s);
  456.  
  457.     /* setup the proper file names */
  458.     bp = curbp;
  459.     strcpy(tmpnam, bp->b_fname);    /* save the original name */
  460.     strcpy(bp->b_fname, bname1);    /* set it to our new one */
  461.  
  462.     /* write it out, checking for errors */
  463.     if (writeout(filnam1) != TRUE) {
  464.         mlwrite(TEXT2);
  465. /*                      "[Cannot write filter file]" */
  466.         strcpy(bp->b_fname, tmpnam);
  467.         return(FALSE);
  468.     }
  469.  
  470.         TTputc('\n');                /* Already have '\r'    */
  471.         TTflush();
  472.         TTclose();                              /* stty to old modes    */
  473.     strcat(line," <fltinp >fltout");
  474.         system(line);
  475.         TTopen();
  476.         TTflush();
  477.         sgarbf = TRUE;
  478.         s = TRUE;
  479.  
  480.     /* on failure, escape gracefully */
  481.     if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
  482.         mlwrite(TEXT3);
  483. /*                      "[Execution failed]" */
  484.         strcpy(bp->b_fname, tmpnam);
  485.         unlink(filnam1);
  486.         unlink(filnam2);
  487.         return(s);
  488.     }
  489.  
  490.     /* reset file name */
  491.     strcpy(bp->b_fname, tmpnam);    /* restore name */
  492.     bp->b_flag |= BFCHG;        /* flag it as changed */
  493.  
  494.     /* and get rid of the temporary file */
  495.     unlink(filnam1);
  496.     unlink(filnam2);
  497.     return(TRUE);
  498. }
  499.  
  500. /* return a system dependant string with the current time */
  501.  
  502. char *PASCAL NEAR timeset()
  503.  
  504. {
  505.     register char *sp;    /* temp string pointer */
  506.     char buf[16];        /* time data buffer */
  507.     extern char *ctime();
  508.  
  509.     time(buf);
  510.     sp = ctime(buf);
  511.     sp[strlen(sp)-1] = 0;
  512.     return(sp);
  513. }
  514.  
  515. #if    COMPLET
  516. /*    FILE Directory routines        */
  517.  
  518. DIR *dirptr = NULL;    /* pointer to the current directory being searched */
  519.  
  520. char path[NFILEN];    /* path of file to find */
  521. char rbuf[NFILEN];    /* return file buffer */
  522. char *nameptr;        /* ptr past end of path in rbuf */
  523.  
  524. /*    do a wild card directory search (for file name completion) */
  525.  
  526. char *PASCAL NEAR getffile(fspec)
  527.  
  528. char *fspec;    /* pattern to match */
  529.  
  530. {
  531.     register int index;        /* index into various strings */
  532.     register int point;        /* index into other strings */
  533.     register int extflag;        /* does the file have an extention? */
  534.  
  535.     /* first parse the file path off the file spec */
  536.     strcpy(path, fspec);
  537.     index = strlen(path) - 1;
  538.     while (index >= 0 && (path[index] != '/' &&
  539.                 path[index] != '\\' && path[index] != ':'))
  540.         --index;
  541.     path[index+1] = 0;
  542.  
  543.     /* check for an extension */
  544.     point = strlen(fspec) - 1;
  545.     extflag = FALSE;
  546.     while (point >= 0) {
  547.         if (fspec[point] == '.') {
  548.             extflag = TRUE;
  549.             break;
  550.         }
  551.         point--;
  552.     }
  553.  
  554.     /* open the directory pointer */
  555.     if (dirptr != NULL) {
  556.         closedir(dirptr);
  557.         dirptr = NULL;
  558.     }
  559.     dirptr = opendir(path);
  560.     if (dirptr == NULL)
  561.         return(NULL);
  562.  
  563.     strcpy(rbuf, path);
  564.     nameptr = &rbuf[strlen(rbuf)];
  565.  
  566.     /* and call for the first file */
  567.     return(getnfile());
  568. }
  569.  
  570. char *PASCAL NEAR getnfile()
  571.  
  572. {
  573.     register struct direct *dp;    /* directory entry pointer */
  574.     register int index;        /* index into various strings */
  575.     struct stat fstat;
  576.  
  577.     /* and call for the next file */
  578. nxtdir:    dp = readdir(dirptr);
  579.     if (dp == NULL)
  580.         return(NULL);
  581.  
  582.     /* check to make sure we skip directory entries */
  583.     strcpy(nameptr, dp->d_name);
  584.     stat(rbuf, &fstat);
  585.     if ((fstat.st_mode & S_IFMT) != S_IFREG)
  586.         goto nxtdir;
  587.  
  588.     /* return the next file name! */
  589.     return(rbuf);
  590. }
  591. #else
  592. char *PASCAL NEAR getffile(fspec)
  593.  
  594. char *fspec;    /* file to match */
  595.  
  596. {
  597.     return(NULL);
  598. }
  599.  
  600. char *PASCAL NEAR getnfile()
  601.  
  602. {
  603.     return(NULL);
  604. }
  605. #endif
  606. #else
  607. unixhello()
  608. {
  609. }
  610. #endif
  611.